/////precompiled////////
#include "precompiled.h"
////////////////////////


#include "prs_Func.h"
using namespace prs;

/******************
// TFVoidNewNode //////////////////////////////////////////////////////////////

//
TFVoidNewNode::TFVoidNewNode(svl::TVariant &VParentNode,prs::TNode &NodeType) : vParentNode(VParentNode)
{
  vThis = this;
  nodeType = NodeType.New();
}

//
void TFVoidNewNode::Func(snt::TParams &Params)
{
  TFVoidNewNode *This = dynamic_cast<TFVoidNewNode*>(Params[0].Pointer());
  prs::TNode *ParentNode = dynamic_cast<prs::TNode*>(This->vParentNode.Pointer());
  prs::TNode *NewNode = This->nodeType->New();

  ParentNode->Children_Add(NewNode,true);
  This->vParentNode = NewNode;
}
*****************************/
/********************
// TFVoidNewNode //////////////////////////////////////////////////////////////

//
snt::TFVoid &TFVoidNewNode::New(svl::TVariant &VParentNode,TNode &NodeType,bool SetParent) 
{
  TFVoidNewNode *P = new TFVoidNewNode;
    P->vParentNode = &VParentNode;
    P->nodeType = NodeType.New();
    P->setParent = SetParent;
  snt::TFVoid &F = snt::TFVoid().New(Func,P->vThis);
    F.SetExt(P);
  return F;
}

//
void TFVoidNewNode::Func(snt::TParams &Params)
{
  TFVoidNewNode *This = dynamic_cast<TFVoidNewNode*>(Params[0].Pointer());
  prs::TAttrNode *ParentNode = dynamic_cast<TAttrNode*>(This->vParentNode->Pointer());
  prs::TNode *NewNode = This->nodeType->New();

  ParentNode->OldChildren.Array.Add(NewNode,true);
  
  if (This->setParent) {
   *This->vParentNode = NewNode;
  }
}
**************************/

// TFuncNewNodeIntoAttr ///////////////////////////////////////////////////////

//
snt::TFVoid &TFuncNewNodeIntoAttr::New(
  svl::TVariant &VNode,
  svl::TString &AttrName,
  TAttrNode &NodeType,
  bool SetParent
)
{
  TFuncNewNodeIntoAttr *P = new TFuncNewNodeIntoAttr;
    P->vNode = &VNode;
    P->attrName = &AttrName;
    P->nodeType = static_cast<TAttrNode*>(NodeType.New());
    P->setParent = SetParent;
  snt::TFVoid &F = snt::TFVoid().New(P,&TFuncNewNodeIntoAttr::Func);
    F.SetExt(P);
  return F;
}

//
snt::TFVoid &TFuncNewNodeIntoAttr::New(
  svl::TVariant &VNode,
  const char *AttrName,
  TAttrNode &NodeType,
  bool SetParent
)
{
  TFuncNewNodeIntoAttr *P = new TFuncNewNodeIntoAttr;
    P->vNode = &VNode;
    P->defAttrName = AttrName;
    P->attrName = &P->defAttrName;
    P->nodeType = static_cast<TAttrNode*>(NodeType.New());
    P->setParent = SetParent;
  snt::TFVoid &F = snt::TFVoid().New(P,&TFuncNewNodeIntoAttr::Func);
    F.SetExt(P);
  return F;
}

//
void TFuncNewNodeIntoAttr::Func(snt::TParams &Params)
{
  TAttrNode *Node = dynamic_cast<TAttrNode*>(vNode->Pointer());

  TAttr *Attr = Node->SearchAttr(*attrName); 
  if (!Attr) {
    Except("Func[!Attr]");
  }

  //////////////////////////////////////////////////////////////////////////
  TAttrPointerBase *AttrPointerBase = dynamic_cast<TAttrPointerBase*>(Attr);
  if (AttrPointerBase) {
    if (AttrPointerBase->GetEAttrPointerType() == AttrPointerBase->EAttrPointerType_NodeOwner) {
      TAttrNode *NewNode = static_cast<TAttrNode*>(nodeType->New());
      AttrPointerBase->SetValueAsPointer(NewNode);

      if (setParent) {
       *vNode = NewNode;
      }
      return;
    }
    Except("Func[!EAttrPointerType_NodeOwner]");
  }

  ////////////////////////////////////////////////////////////////////////////////
  TAttrNodeArrayBase *AttrNodeArrayBase = dynamic_cast<TAttrNodeArrayBase*>(Attr);
  if (AttrNodeArrayBase) {
    TAttrNode *NewNode = static_cast<TAttrNode*>(nodeType->New());
    AttrNodeArrayBase->GetValueAsNodeArray().AddLast(NewNode,true);

    if (setParent) {
     *vNode = NewNode;
    }
    return;
  }

  Except("Func[else]");
}
